package com.gxa.learning.pc.controller;

import com.gxa.learning.core.common.ExceptionCode;
import com.gxa.learning.core.common.JsonResult;
import com.gxa.learning.core.exception.BusinessException;
import com.gxa.learning.core.pojo.*;
import com.gxa.learning.core.util.OssUtil;
import com.gxa.learning.pc.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 培训计划的接口
 *
 * @author YXQ
 * @date 2021/12/2 18:10
 */
@RestController
@Api(tags = "培训计划的接口")
@RequestMapping("/trainPlan")
public class TrainPlanController {

    @Autowired
    TrainPlanService trainPlanService;

    @Autowired
    FlowPathNodeService flowPathNodeService;

    @Autowired
    ExamineApprovalService examineApprovalService;

    @Autowired
    TrainPlanBudgetService trainPlanBudgetService;

    /**
     * 等待审批需要的redis的键 -->  审批流程的id
     * waitExamine: + userId   ->  审批流程的id
     */
    public static final String WAIT_EXAMINE = "waitExamine:";

    public static final String FILE = "file";

    /**
     * 定义一个数据常量
     */
    public static final Integer ZERO = 0;

    @Autowired
    TypeService typeService;

    @GetMapping("/getPlanType")
    @ApiOperation("获取计划状态的接口")
    Map<String, Object> getPlanType() {
        // 暂时只有1.审批中2.审批通过3.审批未通过
        // 弄假数据反给前端
        Map<String, Object> map1 = new HashMap<>(2);
        List<Map<String, Object>> list = new ArrayList<>(3);
        map1.put("id", 1);
        map1.put("planType", "审核中");
        list.add(map1);
        Map<String, Object> map2 = new HashMap<>(2);
        map2.put("id", 2);
        map2.put("planType", "审核通过");
        list.add(map2);
        Map<String, Object> map3 = new HashMap<>(2);
        map3.put("id", 3);
        map3.put("planType", "审核未通过");
        list.add(map3);
        // 生成JsonResult对象给前端返回数据
        JsonResult jsonResult = new JsonResult();
        // 添加返回的数据
        jsonResult.setCode("1");
        jsonResult.setMsg("查询成功");
        jsonResult.setData(list);
        // 返回给前端
        return jsonResult.getDataMap();
    }

    @GetMapping("/getType")
    @ApiOperation("获取培训计划的所有的所属类别的接口")
    Map<String, Object> getType() {
        List<Type> types = typeService.selectAll();
        // 生成JsonResult对象给前端返回数据
        JsonResult jsonResult = new JsonResult();
        // 添加返回的数据
        jsonResult.setCode("1");
        jsonResult.setMsg("查询成功");
        jsonResult.setData(types);
        // 返回给前端
        return jsonResult.getDataMap();
    }

    @GetMapping("/getPlanList")
    @ApiOperation("获取培训计划列表的接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "计划名称", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "planType", value = "计划状态", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "type", value = "所属类目", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "page", value = "页码", dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "size", value = "每页记录条数", dataType = "Integer", paramType = "query"),
    })
    Map<String, Object> getPlanList(String name, String planType, String type, Integer page, Integer size) {
        // 这里查看详情，需要预算，和审批节点
        List<TrainPlanVo> trainPlanVos = trainPlanService.selectQueryAndPage(name, planType, type, page, size);
        // 获取总的记录数
        int size1 = trainPlanVos.size();
        // 应该给前端返回的分页后的数据
        List<TrainPlanVo> trainPlanVosByPage = new ArrayList<>(size1);
        // 生成JsonResult对象给前端返回数据
        JsonResult jsonResult = new JsonResult();
        // 添加返回的数据
        jsonResult.setCode("1");
        jsonResult.setMsg("查询成功");
        jsonResult.put("count", size1);
        // 根绝page和size进行分页（物理，手动分页）,然后返回对应数据给前端
        if (page != null && !ZERO.equals(page)) {
            if (size != null && !ZERO.equals(size)) {
                // page和size都不为null或者0时
                if (size1 == 0) {
                    jsonResult.setData(trainPlanVos);
                } else {
                    // 页数
                    int pageNum = size1 / size;
                    // 如果不能整除页数+1
                    if (size1 % size != 0) {
                        pageNum = size1 / size + 1;
                    }
                    // 遍历总的结果集，把分页的部分数据传入分页后的集合
                    for (int i = 0; i < size; i++) {
                        if ((page - 1) * size + i >= size1) {
                            break;
                        }
                        // 从(page - 1) * size开始的size或者小于size条数据装入新的集合中
                        trainPlanVosByPage.add(trainPlanVos.get((page - 1) * size + i));
                    }
                    // 传给前端
                    jsonResult.setData(trainPlanVosByPage);
                }
            }
        } else {
            jsonResult.setData(trainPlanVos);
        }
        // 返回给前端
        return jsonResult.getDataMap();
    }

    @GetMapping("/getPlanDetails")
    @ApiOperation("获取计划的详细信息的接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "待查看的计划的id", required = true, dataType = "Long", paramType = "query"),
    })
    Map<String, Object> selectTrainPlanDetails(Long id) {
        TrainPlanVo trainPlanVo = trainPlanService.selectTrainPlanDetails(id);
        // 生成JsonResult对象给前端返回数据
        JsonResult jsonResult = new JsonResult();
        // 添加返回的数据
        jsonResult.setCode("1");
        jsonResult.setMsg("查询成功");
        jsonResult.setData(trainPlanVo);
        // 返回给前端
        return jsonResult.getDataMap();
    }

    @GetMapping("/getMyExamineList")
    @ApiOperation("获取”我的审批”中”待审批/已审批“的计划的接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "当前登录用户的id", required = true, dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "planType", value = "计划状态:待审批/已审批==>0/1", required = true, dataType = "int", paramType = "query")
    })
    Map<String, Object> getMyExamineList(Long id, Integer planType) {
        // 生成JsonResult对象给前端返回数据
        JsonResult jsonResult = new JsonResult();
        // 给前端的集合
        List<TrainPlanVo> trainPlanVos;
        // 待审批与已审批调用不同方法
        if (planType == null || ZERO.equals(planType)) {
            // 获取待审批计划
            trainPlanVos = trainPlanService.selectWaitExamineList(id);
            // 我的审批的待审批数量
            jsonResult.put("waitExaminePlanCount", trainPlanVos.size());
        } else {
            // 获取已审批计划
            trainPlanVos = trainPlanService.selectAlreadyExamineList(id);
            // 我的审批的已审批数量
            jsonResult.put("alreadyExaminePlanCount", trainPlanVos.size());
        }
        // 添加返回的数据
        jsonResult.setCode("1");
        jsonResult.setMsg("查询成功");
        jsonResult.setData(trainPlanVos);
        jsonResult.put("count", trainPlanVos.size());
        jsonResult.put("trainType", "培训计划");
        // 返回给前端
        return jsonResult.getDataMap();
    }

    @GetMapping("/getMyExamineApprovalsList")
    @ApiOperation("获取”我的审批”的”审批进度“的接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "当前登录用户的id", required = true, dataType = "Long", paramType = "query")
    })
    Map<String, Object> getMyExamineApprovalsList(Long id) {
        // 生成JsonResult对象给前端返回数据
        JsonResult jsonResult = new JsonResult();
        if (id == null) {
            id = 0L;
        }
        List<TrainPlanVo> trainPlanVos = trainPlanService.selectGetMyExamineApprovalsList(id);
        // 添加返回的数据
        jsonResult.setCode("1");
        jsonResult.setMsg("查询成功");
        jsonResult.setData(trainPlanVos);
        jsonResult.put("count", trainPlanVos.size());
        // 返回给前端
        return jsonResult.getDataMap();
    }

    @GetMapping("/agreeOrRefuse")
    @ApiOperation("计划的同意或者拒绝的接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "当前登录用户的id", required = true, dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "planId", value = "审批的计划的id", required = true, dataType = "Long", paramType = "query"),
            @ApiImplicitParam(name = "option", value = "意见：同意/不同意或者0/1", required = true, dataType = "Long", paramType = "query"),
    })
    Map<String, Object> agreeOrRefuse(Long id, Long planId, String option) throws BusinessException {
        // 生成JsonResult对象给前端返回数据
        JsonResult jsonResult = new JsonResult();
        // 审批意见
        // 如果用0/1表示不同意或者同意
        String agree = "1";
        String notAgree = "0";
        if (agree.equals(option)) {
            option = "同意";
        } else if (notAgree.equals(option)) {
            option = "不同意";
        }
        // 获取 待审批 的计划，防止用户误操作
        List<TrainPlanVo> waitTrainPlanVos = trainPlanService.selectWaitExamineList(id);
        if (waitTrainPlanVos.size() == 0) {
            // 您没有 待审批 的计划
            throw new BusinessException(ExceptionCode.NOT_HAVE_TRAIN_PAIN_EXAMINE);
        }
        // 获取 已审核 的计划，防止重复提交
        List<TrainPlanVo> trainPlanVos = trainPlanService.selectAlreadyExamineList(id);
        // 遍历看当前提交的计划是否是 已审核 的计划
        for (TrainPlanVo trainPlanVo : trainPlanVos) {
            //  通过id校验
            if (trainPlanVo.getId().equals(planId)) {
                // 不能重复提交评价
                throw new BusinessException(ExceptionCode.NOT_ALLOW_SUBMIT_AGAIN);
            }
        }
        // 通过用户id和当前计划的id值，找到当前 流程节点的id 赋值给流程节点的对象上
        FlowPathNode flowPathNode = trainPlanService.selectByUserAndPlan(id, planId);
        // 需要改动的字段
        // 审批时间为当前时间
        flowPathNode.setOperationTime(new Date());
        // 审批意见
        flowPathNode.setOpinion(option);
        // 审批状态
        flowPathNode.setState(true);
        // 审批计划1.对当前流程节点的数据做出修改
        flowPathNodeService.updateById(flowPathNode);
        // 检查 意见征询节点的数量 与 当前已同意的意见的数量
        // 意见征询节点的数量
        ExamineApproval examineApproval = trainPlanService.selectOpinionCount(planId);
        // 意见征询节点的数量
        Integer opinionCount = examineApproval.getOpinion();
        // 当前已同意的意见的数量
        Integer alreadyAgreeCount = trainPlanService.selectAlreadyAgreeCount(planId);
        // 当前已不同意的意见的数量
        Integer alreadyNotAgreeCount = trainPlanService.selectAlreadyNotAgreeCount(planId);
        // 获取流程节点的总数
        Integer examineApprovalCount = trainPlanService.selectExamineApprovalCount(planId);
        // 如果 当前已同意的意见的数量 超过 意见征询节点的数量 将审批流程的意见状态设置为
        if (alreadyAgreeCount >= opinionCount) {
            // 设置审批的状态为 已通过
            examineApproval.setState(1);
        }
        // 已经拒绝的节点数大于总节点数-征询个数   4(拒绝)  5(总数)  2(征询节点)
        if (alreadyNotAgreeCount > (examineApprovalCount - opinionCount)) {
            // 设置审批的状态为 已驳回
            examineApproval.setState(2);
        }
        // 更新审批流程中计划的状态
        examineApprovalService.updateById(examineApproval);
        // 添加返回的数据
        jsonResult.setCode("1");
        jsonResult.setMsg("审核成功");
        // 返回给前端
        return jsonResult.getDataMap();
    }

    @PostMapping("/addTrainPlan")
    @ApiOperation("添加计划的接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "map", value = "添加审批计划的参数", required = true, dataType = "map", paramType = "body"),
    })
    Map<String, Object> addTrainPlan(@RequestBody Map<String, Object> map) throws BusinessException, ParseException {
        System.out.println("-----------------");
        System.out.println("map:    " + map);
        // 创建培训计划对象添加时用
        TrainPlan trainPlan = new TrainPlan();
        // 做数据校验
        Object o1 = map.get("title");
        String title = null;
        if (o1 != null) {
            title = o1.toString();
        }
        // 添加到 培训计划 的字段中
        trainPlan.setTitle(title);
        // 做数据校验
        Object o2 = map.get("start");
        System.out.println(o2);
        // 设定日期转换格式
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        // 创建日期对象
        Date startDate = null;
        if (o2 != null) {
            // 开始时间的字符串
            String start = o2.toString();
            // 将日期字符串转化为日期对象
            startDate = format.parse(start);
        }
        // 添加到培训计划的开始时间的字段上
        trainPlan.setStart(startDate);
        // 做数据校验
        Object o3 = map.get("end");
        // 创建日期对象
        Date endDate = null;
        if (o3 != null) {
            // 结束时间的字符串
            String end = o3.toString();
            // 将日期字符串转化为日期对象
            endDate = format.parse(end);
        }
        // 添加到培训计划的结束时间的字段上
        trainPlan.setEnd(endDate);
        // 做数据校验
        Object o4 = map.get("planType");
        String planType = null;
        if (o4 != null) {
            planType = o4.toString();
        }
        // 添加到培训计划的 计划状态 的字段上
        trainPlan.setPlanType(planType);
        // 做数据校验
        Object o5 = map.get("document");
        String document = "";
        if (o5 != null) {
            document = o5.toString();
        }
        // 添加到培训计划的 计划的附件 的字段上
        trainPlan.setDocument(document);
        // 通过附件名字，将附件从临时目录加载到正式目录中
        // 获取附件的真实文件名
        System.out.println("document:  " + document);
        String substring = document.substring(document.lastIndexOf("/") + 1);
        System.out.println("文件名：  " + substring);
        // 正式目录
        String fileName = "learning/trainPlanDocument/official/" + substring;
        // 先看临时目录中是否存在这个文件
        boolean b = OssUtil.fileExist("learning/trainPlanDocument/temp/" + substring);
        if (b) {
            // 调用阿里云复制文件的操作
            OssUtil.copyFile("learning/trainPlanDocument/temp/" + substring, fileName);
        } else {
            // 文件不存在，或上传失败，请重试
            throw new BusinessException(ExceptionCode.FILE_NOT_EXIT);
        }
        // 计划的创建时间为现在的时间
        trainPlan.setCreate(new Date());
        TrainPlan insert = trainPlanService.insert(trainPlan);
        // 获取添加后的id字段，作为添加部门的关联的id使用
        Long id = insert.getId();
        // 从前端参数中获取部门信息
        List<Map<String, Object>> departmentList = (List) map.get("budgetList");

        // 遍历部门信息添加到数据库中
        for (Map<String, Object> stringObjectMap : departmentList) {
            System.out.println("部门信息：" + stringObjectMap);
            // 创建部门对象，用于向数据库添加数据
            TrainPlanBudget trainPlanBudget = new TrainPlanBudget();
            // 设置部门对象与计划关联的id
            trainPlanBudget.setPlanId(id);
            // 从前端参数中获取部门名
            Object department = stringObjectMap.get("department");
            if (department != null) {
                // 将部门名添加到部门对象中
                trainPlanBudget.setDepartment(department.toString());
            }
            // 从前端参数中获取预算金额
            Object budget = stringObjectMap.get("budget");
            if (budget != null) {
                trainPlanBudget.setBudget(Long.parseLong(budget.toString()));
            }
            // 调用service方法添加到数据库
            trainPlanBudgetService.insert(trainPlanBudget);
        }
        // 生成JsonResult对象给前端返回数据
        JsonResult jsonResult = new JsonResult();
        // 添加返回的数据
        jsonResult.setCode("1");
        jsonResult.setMsg("添加成功");
        // 返回给前端
        return jsonResult.getDataMap();
    }
}
